import re
from rest_framework import serializers
from django.contrib.auth.hashers import make_password
from rest_framework_jwt.settings import api_settings
from django_redis import get_redis_connection
from .models import User
from .utils import get_user


class UserModelSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(min_length=4,
                                     max_length=6,
                                     required=True,
                                     help_text='短信验证码',
                                     write_only=True)
    token = serializers.CharField(max_length=1024,
                                  read_only=True,
                                  help_text='token认证字符串')

    class Meta:
        model = User
        fields = ['id', 'username', 'mobile', 'password', 'sms_code', 'token']
        extra_kwargs = {
            'id': {
                'read_only': True,
            },
            'username': {
                'read_only': True,
            },
            'password': {
                'write_only': True,
            },
            'mobile': {
                'write_only': True,
            }
        }

    def validate(self, attrs):
        mobile = attrs.get('mobile')
        sms_code = attrs.get('sms_code')
        password = attrs.get('password')

        # 校验手机号的格式
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError('请正确填写手机号！')
        user = get_user(mobile)
        if user is not None:
            raise serializers.ValidationError('该手机号已经被注册！')

        # todo 校验短信验证码是否正确
        redis_conn = get_redis_connection('sms_code')
        redis_sms_code = redis_conn.get('sms_%s' % mobile).decode()
        if sms_code != redis_sms_code:
            raise serializers.ValidationError('验证码输入有误，请核对后重新输入！')
        return attrs

    def create(self, validated_data):
        validated_data.pop('sms_code')
        raw_password = validated_data.get('password')
        hash_password = make_password(raw_password)
        mobile = validated_data.get('mobile')
        user = User.objects.create(
            mobile=mobile,
            password=hash_password,
            username=mobile,
        )
        # 手动生成'JWT'认证字符串
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token

        return user
